!-------------------------------------------------------------LICENSE--------------------------------------------------------------!
!                                                                                                                                  !
!The MAP code is written in Fortran language for magnetohydrodynamics (MHD) calculation with the adaptive mesh refinement (AMR)    !
!and Message Passing Interface (MPI) parallelization.                                                                              !
!                                                                                                                                  !
!Copyright (C) 2012                                                                                                                !
!Ronglin Jiang                                                                                                                     !
!rljiang@ssc.net.cn                                                                                                                !
!585 Guoshoujing Road. Pudong, Shanghai, P.R.C. 201203                                                                             !
!                                                                                                                                  !
!This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License         !
!as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.             !
!                                                                                                                                  !
!This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of    !
!MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.                        !
!                                                                                                                                  !
!You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software     !
!Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.                                                   !
!                                                                                                                                  !
!-------------------------------------------------------------LICENSE--------------------------------------------------------------!

!==================================================================================================================================|
subroutine block_boundary_physi(current, dir, sides, pos,                                                                          &
   ro_flag, mx_flag, my_flag, mz_flag, bx_flag, by_flag, bz_flag, en_flag, po_flag, lv)
!==================================================================================================================================|

   use parameters
   use block_define

   implicit none

   character(1), intent(in) :: dir, sides, pos
   integer(4), optional, intent(in) :: lv
   logical(4) :: ro_flag, mx_flag, my_flag, mz_flag, bx_flag, by_flag, bz_flag, en_flag, po_flag
   type(block), pointer, intent(inout) :: current

   integer(4) :: i_neigh, i_dim
   integer(4), dimension(sys) :: bnd

!----------------------------------------------------------------------------------------------------------------------------------|
   if (dir .eq. 'x') then
      i_dim = 1
   elseif (dir .eq. 'y') then
      i_dim = 2
   else
      write (*, *) 'Direction error from block_boundary_physi.'
      stop
   endif
      
   if (sides .eq. 'l') then
      i_neigh = 1
   elseif (sides .eq. 'h') then
      i_neigh = 2
   else
      write (*, *) 'Sides error from block_boundary_physi.'
      stop
   endif

   if (pos .eq. 'e') then
      bnd = bnd_exterior(:, i_neigh, i_dim)
   elseif (pos .eq. 'i') then
      bnd = bnd_interior(:, i_neigh, i_dim, lv)
   else
      write (*, *) 'Boundary type error from block_boundary_physi.'
      stop
   endif

   select case (bnd(1))
   case (1:2)
      if (ro_flag) call bnd_free_2d (current%ro, nx_block, ny_block, ng, dir, sides)
      if (po_flag) call bnd_free_2d (current%po, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (ro_flag) call bnd_symp_2d (current%ro, nx_block, ny_block, ng, dir, sides)
      if (po_flag) call bnd_symp_2d (current%po, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (ro_flag) call bnd_symn_2d (current%ro, nx_block, ny_block, ng, dir, sides)
      if (po_flag) call bnd_symn_2d (current%po, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (ro_flag) call bnd_line_2d (current%ro, nx_block, ny_block, ng, dir, sides)
      if (po_flag) call bnd_line_2d (current%po, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(2))
   case (1:2)
      if (mx_flag) call bnd_free_2d (current%mx, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (mx_flag) call bnd_symp_2d (current%mx, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (mx_flag) call bnd_symn_2d (current%mx, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (mx_flag) call bnd_line_2d (current%mx, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(3))
   case (1:2)
      if (my_flag) call bnd_free_2d (current%my, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (my_flag) call bnd_symp_2d (current%my, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (my_flag) call bnd_symn_2d (current%my, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (my_flag) call bnd_line_2d (current%my, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(4))
   case (1:2)
      if (mz_flag) call bnd_free_2d (current%mz, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (mz_flag) call bnd_symp_2d (current%mz, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (mz_flag) call bnd_symn_2d (current%mz, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (mz_flag) call bnd_line_2d (current%mz, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(5))
   case (1:2)
      if (bx_flag) call bnd_free_2d (current%bx, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (bx_flag) call bnd_symp_2d (current%bx, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (bx_flag) call bnd_symn_2d (current%bx, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (bx_flag) call bnd_line_2d (current%bx, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(6))
   case (1:2)
      if (by_flag) call bnd_free_2d (current%by, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (by_flag) call bnd_symp_2d (current%by, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (by_flag) call bnd_symn_2d (current%by, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (by_flag) call bnd_line_2d (current%by, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(7))
   case (1:2)
      if (bz_flag) call bnd_free_2d (current%bz, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (bz_flag) call bnd_symp_2d (current%bz, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (bz_flag) call bnd_symn_2d (current%bz, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (bz_flag) call bnd_line_2d (current%bz, nx_block, ny_block, ng, dir, sides)
   end select

   select case (bnd(8))
   case (1)
      if (en_flag) call bnd_free_2d (current%en, nx_block, ny_block, ng, dir, sides)
   case (2)
      if (en_flag) call bnd_grpr_2d (current%ro, current%mx, current%my, current%mz, current%bx, current%by,                       &
         current%bz, current%en, current%gx, current%gy, current%x, current%y, gm, nx_block, ny_block, ng, dir, sides)
   case (3)
      if (en_flag) call bnd_symp_2d (current%en, nx_block, ny_block, ng, dir, sides)
   case (4)
      if (en_flag) call bnd_symn_2d (current%en, nx_block, ny_block, ng, dir, sides)
   case (5)
      if (en_flag) call bnd_line_2d (current%en, nx_block, ny_block, ng, dir, sides)
   end select

   if (any(bnd .eq. 8)) then
      if (ini_value_save_flag .eq. 1) then
         call bnd_user(current%ro, current%mx, current%my, current%mz,                                                             &
            current%bx, current%by, current%bz, current%en, current%gx, current%gy, current%po,                                    &
            current%ro0, current%mx0, current%my0, current%mz0, current%bx0, current%by0, current%bz0, current%en0,                &
            current%x, current%y, nx_block, ny_block, dir, sides)
      else
         write(*, *) 'ini_value_save_flag should equal to 1,'
         call mpi_abort(mpi_comm_world, 1, error)
      endif
   endif

   if (any(bnd .eq. 9)) call bnd_fixe_2d(current%ro, current%mx, current%my, current%mz,                                           &
      current%bx, current%by, current%bz, current%en, current%gx, current%gy, current%po, current%x, current%y,                    &
      nx_block, ny_block, ng, dir, sides)

   if (bx_flag .or. by_flag .or. bz_flag)                                                                                          &
      call bnd_pote_2d (current%az, current%bx, current%by, current%x, current%y, nx_block, ny_block, ng, dir, sides)

!----------------------------------------------------------------------------------------------------------------------------------|
   return
end subroutine block_boundary_physi
